package difed.restaurante.util;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import difed.restaurante.util.test.ReverseGeocoder;

public class GeocoderUtil {
    
    public interface ResultadoLocalizacion {
        
        void localizacionObtenida(Location location);
        
    }

    private static final int NUM_TRIES = 3;
    
    public static void recuperaDireccion(Context context, ResultadoLocalizacion resultado) {
        // FIXME - Para probarlo en el navegador, poner latitud y longitud propios
        if ("sdk".equals(Build.PRODUCT)) {
            CustomLog.debug("GeocoderUtil", "Localizacion en emulador");
            Location loc = new Location("Prueba");
            loc.setLatitude(37.407017);
            loc.setLongitude(-6.005788);
            resultado.localizacionObtenida(loc);
        } else {
            LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            MyLocationListener listener = new MyLocationListener(context, resultado);
            //if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
           //     lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
          //  } else 
            if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);                
            }
        }
    }
    
    public static Address calculaDireccion(Context context, Location loc) {
        Address result = null;
        if (loc != null) {
            Geocoder gcd = new Geocoder(context);
            List<Address> addresses = addresses(gcd, loc.getLatitude(), loc.getLongitude());
            String province = null;
            String locality = null;
            if (addresses != null) {
                for (Address address : addresses) {
                    province = address.getSubAdminArea();
                    locality = address.getLocality();
                    if (province != null && locality != null) {
                        result = address;
                        break;
                    }
                }
            }
        }
        return result;
    }
    
    private static List<Address> addresses(Geocoder g, double latitude, double longitude) {
        List<Address> addresses = null;
        int i = 0;
        while (i < NUM_TRIES && addresses == null) {
            if ("sdk".equals(Build.PRODUCT)) {
                CustomLog.debug("GeocoderUtil", "Geocoder doesn't work under emulation.");
                addresses = ReverseGeocoder.getFromLocation(latitude, longitude, 3);
            } else {
                try {
                    addresses = g.getFromLocation(latitude, longitude, 3);
                } catch (IOException e) {
                    CustomLog.error("GeocoderUtil", e.getMessage());
                }
            }
            i++;
        }
        if (addresses == null || addresses.isEmpty()) {
            return null;
        } else {
            return addresses;
        }
    }
    
    static class MyLocationListener implements LocationListener {
        
        private Context context;
        private ResultadoLocalizacion resultado;
        
        public MyLocationListener(Context context, ResultadoLocalizacion resultado) {
            this.context = context;
            this.resultado = resultado;
        }
        
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            String providerStatus = "Desconocido";
            if (status == LocationProvider.AVAILABLE) {
                providerStatus = "Disponible";
            } else if (status == LocationProvider.OUT_OF_SERVICE) {
                providerStatus = "Fuera de Servicio";
            } else if (status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
                providerStatus = "No disponible temporalmente";
            }
            Log.d("MisRestaurantes", "onStatusChanged " + provider + " (" + providerStatus + ")");
        }
        
        @Override
        public void onProviderEnabled(String provider) {
            
        }
        
        @Override
        public void onProviderDisabled(String provider) {
            Log.d("MisRestaurantes", "Desactivando listener");
            LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            lm.removeUpdates(this);
            resultado.localizacionObtenida(null);
        }
        
        @Override
        public void onLocationChanged(Location location) {
            Log.d("MisRestaurantes", "Desactivando listener");
            LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            lm.removeUpdates(this);
            resultado.localizacionObtenida(location);
        }
    };

}
